<?php
/**
 * > トップページ
 *
 * LICENSE: Miracle Maple by Mirage is licensed
 * under a Creative Commons 表示-非営利-継承 2.1 日本 License.
 *
 * @category   controller
 * @package    maple-story.jp
 * @subpackage index
 * @version    8.0.0
 * @link       http://maple-story.jp/
 * @since      File available since Release 8.0.0
 * @copyright  Copyright 2011 Miracle Maple
 * @license    http://creativecommons.org/licenses/by-nc-sa/2.1/jp/     Creative Commons BY-NC-SA
 */
 
class ImportController extends Zend_Controller_Action
{
	/**
	 * WZ 解析対象ディレクトリ
	 * @var string
	 */
	private $_expath;

	/**
	 * インポート設定
	 * @var Zend_Config_Ini
	 */
	private $_config;
	
	/**
	 * インポートツール用
	 * 画像出力
	 * @var Zend_Controller_Action_Helper
	 */
	private $_dumper;

	/**
	 * 画像出力パス
	 * @var string
	 */
	private $_dumpDirectory;

	/**
	 * コンストラクタ
	 */
	public function init()
	{
		// 本番環境での動作を許可しない
		if (APPLICATION_ENV == 'production') {
			throw new Exception('Not Found');
			return false;
		}
		
		// 設定ファイル読み込み
		$this->_config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/import.ini');
		$this->_expath = $this->_config->wzpath . '/'
					   . $this->_config->version;
					   
		$this->_dumper = $this->_helper->getHelper('Import');
		$this->_dumpDirectory = realpath($_SERVER['DOCUMENT_ROOT'] . $this->_config->dumppath);
	}
		
    /**
     * トップページ
     */
    public function indexAction()
    {
    }    
	
	/**
	 * モンスターデータインポート
	 */
	public function monsterAction()
	{
		$monster = new Model_TrnMonster();
		$monsterDrop = new Model_TrnMonsterDrop();
		
		// 各モンスター情報取得
		$directory = $this->_expath . $this->_config->monster->file->data;
		$fileList = $this->_getAllFiles($directory);
		$columnList = $this->_config->monster->column->toArray();
		
		// WID リストからモンスターデータ取得 (新規/更新の判別用)
		$widList = array_map(array($this, '_getWid'), $fileList);
		$widRowSet = $monster->getByWid($widList);
		
		// モンスター名称リスト取得
		$nameFile = $this->_expath . $this->_config->monster->file->name;
		$domName = new Zend_Dom_Query(file_get_contents($nameFile));

		// モンスターブック情報取得
		$bookFile = $this->_expath . $this->_config->monster->bookfile->name;
		$domBook = new Zend_Dom_Query(file_get_contents($bookFile));

		// モンスター情報の再構成および保存
		foreach ($fileList as $fileName) {
			$row = new Model_TrnMonster();
			
			// WID 検査 (新規か更新かを判別)
			$wid = $this->_getWid($fileName);
			$row->wid = $wid;
			if (isset($widRowSet[$wid])) {
				$row->id = $widRowSet[$wid]->id;
			}

			// モンスター名称取得 (from String.wz/Mob.img.xml)
			$domList = $domName->query('imgdir[name="' . (int)$row->wid . '"]');		
			foreach ($domList as $domElement) {
				foreach ($domElement->childNodes as $domNode) {
					if ($domNode->nodeName == "string") {
						$row->name = $domNode->getAttribute('value');
					}
				}
			}

			// モンスターブック情報取得 (from String.wz/MonsterBook.img.xml)
			$domList = $domBook->query('imgdir[name="' . (int)$row->wid . '"]');
			foreach ($domList as $domElement) {
				foreach ($domElement->childNodes as $domNode) {
					if ($domNode->nodeName == 'string' && $domNode->getAttribute('name') == 'episode') {
						$row->description = str_replace('\n', PHP_EOL, $domNode->getAttribute('value'));
					} else if ($domNode->nodeName == 'imgdir' && $domNode->getAttribute('name') == 'reward') {
						$monsterDrop->clear($wid);
						foreach ($domNode->childNodes as $domNodeValue) {
							if ($domNodeValue->nodeName == 'int') {
								$monsterDrop->save($wid, $domNodeValue->getAttribute('value'));
							}
						}
					}
				}
			}

			// モンスター詳細 XML より各パラメータ取得
			$info = $this->_getInfoParameter($directory . '/' . $fileName);
			foreach ($columnList as $sourceName => $columnName) {
				if (isset($info[$sourceName])) {
					$row->$columnName = $info[$sourceName];
				}
			}
			
			$this->_createMonsterImg($directory . '/' . $fileName);
			
			// 時間を取得
			$now = new DateTime();
			$row->update_datetime = $now->format('Y-m-d H:i:s');
			$row->update_user = 'admin';
			
			// 新規登録の場合のみ
			if (!isset($row->id)) {
				$row->since = $this->_config->version;
				$row->insert_datetime = $now->format('Y-m-d H:i:s');
				$row->insert_user = 'admin';
			}

			$row->save();
		}
	}
	
	/**
	 * アイテムデータインポート
	 */
	public function itemAction()
	{
		// 各アイテム情報取得
		$directory = $this->_expath . $this->_config->item->file->data;
		$subDirectories = $this->_getAllFiles($directory);
		$item = array();
		foreach ($subDirectories as $subDirectory) {
			$fileList = $this->_getAllFiles($directory . '/' . $subDirectory);
			
			// アイテム名称リスト取得
			$nameFile = $this->_expath . str_replace('{SUBDIR}', $subDirectory, $this->_config->item->file->name);
			$nameFile = str_replace('Install', 'Ins', $nameFile);
			$domName = new Zend_Dom_Query(file_get_contents($nameFile));

			$subCategory = array();
			foreach ($fileList as $fileName) {
				$filePath = $directory . '/' . $subDirectory . '/' . $fileName;
				$domItem = new Zend_Dom_Query(file_get_contents($filePath));
				
				$fileId = str_replace('.xml', '', $fileName);
				$domList = $domItem->query('imgdir[name*="img"]');
				
				$rowsetItem = array();
				foreach ($domList as $domElement) {
					foreach ($domElement->childNodes as $domNode) {
						if ($domNode->nodeName == "#text") {
							continue;
						}
						
						$wid = (int)$domNode->getAttribute('name');
						foreach ($domNode->childNodes as $domChildNode) {
							if ($domChildNode->nodeName == "#text") {
								continue;
							}
							$property = array();
							foreach ($domChildNode->childNodes as $domProperty) {
								switch ($domProperty->nodeName) {
									case "#text":
										continue;
										break;
									case "canvas":
										$property[$domProperty->getAttribute('name')] = array(
											'basedata' => $domProperty->getAttribute('basedata'),
											'width' => $domProperty->getAttribute('width'),
											'height' => $domProperty->getAttribute('height')
										);
												
										foreach ($domProperty->childNodes as $domVector) {
											if ($domVector->nodeName == "vector") {
												$property[$domProperty->getAttribute('name')][$domVector->getAttribute('name')] = array(
													'x' => $domVector->getAttribute('x'),
													'y' => $domVector->getAttribute('y')
												);
											}
										}
										
										// 画像の保存処理
										$filePath = $this->_config->item->file->data . '/' . (int)$fileId . '/' . (int)$wid;
										$filePath = str_replace('.wz', '', strtolower($filePath));
										$fileName = $domProperty->getAttribute('name') . '.png';
										$this->_dumper->dumpImage($property[$domProperty->getAttribute('name')]['basedata'],
																  $this->_dumpDirectory . $filePath . '/' . $fileName);
										
										break;
									default:
									case "int":
										$property[$domProperty->getAttribute('name')] = $domProperty->getAttribute('value');
								}
							}
							
							$rowsetItem[$wid][$domChildNode->getAttribute('name')] = $property;
						}
						
						// String.wz から名称を取得
						if (is_null($domName->getDocument())) {
							continue;
						}
						$domNameList = $domName->query('imgdir[name="' . $wid . '"]');	
						foreach ($domNameList as $domNameElement) {
							foreach ($domNameElement->childNodes as $domNameNode) {
								if ($domNameNode->nodeName == "#text") {
									continue;
								}
								
								$param = $domNameNode->getAttribute('name');
								$rowsetItem[$wid][$param] = $domNameNode->getAttribute('value');
							}
						}
					}
				}
				
				$this->_setItemRowSet($rowsetItem);
			}		
		}
	}
	
	/**
	 * 装備データエクスポート
	 */
	public function equipmentAction()
	{
		// 装備分類名称
		$equipmentGroup = new Model_MstEquipmentGroup();
		$arrEquipmentGorup = $equipmentGroup->fetchAllArray('wid', 'directory');

		// データファイル取得
		$directory = $this->_expath . $this->_config->equipment->file->data;
		$subDirectories = $this->_getAllFiles($directory);
		
		// 装備名称リスト取得
		$nameFile = $this->_expath . $this->_config->equipment->file->name;
		$domName = new Zend_Dom_Query(file_get_contents($nameFile));
		
		$rowsetEquipment = array();
		foreach ($subDirectories as $subDirectory) {
			$fileList = $this->_getAllFiles($directory . '/' . $subDirectory);
			foreach ($fileList as $fileName) {
				$filePath = $directory . '/' . $subDirectory . '/' . $fileName;
				$fileId = str_replace('.img.xml', '', $fileName);
				
				// 装備名称取得
				$wid = (int)$fileId;
				$rowsetEquipment[$wid] = array();
				$domNameList = $domName->query('imgdir[name="' . $wid . '"]');	
				foreach ($domNameList as $domNameElement) {
					foreach ($domNameElement->childNodes as $domNameNode) {
						if ($domNameNode->nodeName == "#text") {
							continue;
						}
						
						$param = $domNameNode->getAttribute('name');
						$rowsetEquipment[$wid][$param] = $domNameNode->getAttribute('value');
					}
				}
						
				$domEquipment = new Zend_Dom_Query(file_get_contents($filePath));
				$domList = $domEquipment->query('imgdir[name="info"]');
				foreach ($domList as $domElement) {
					$property = array();
					foreach ($domElement->childNodes as $domProperty) {
						switch ($domProperty->nodeName) {
							case "#text":
								continue;
								break;
							case "canvas":
								break;
								$property[$domProperty->getAttribute('name')] = array(
									'basedata' => $domProperty->getAttribute('basedata'),
									'width' => $domProperty->getAttribute('width'),
									'height' => $domProperty->getAttribute('height')
								);
										
								foreach ($domProperty->childNodes as $domVector) {
									if ($domVector->nodeName == "vector") {
										$property[$domProperty->getAttribute('name')][$domVector->getAttribute('name')] = array(
											'x' => $domVector->getAttribute('x'),
											'y' => $domVector->getAttribute('y')
										);
									}
								}
								
								// 画像の保存処理
								$groupCd = substr("000" . $fileId, -7, 3);
								if (isset($arrEquipmentGorup[$groupCd])) {
									$groupCd = strtolower($arrEquipmentGorup[$groupCd]);
								}									
								$filePath = $this->_config->equipment->file->data . '/' . $groupCd . '/' . (int)$wid;
								$filePath = str_replace('.wz', '', strtolower($filePath));
								$fileName = $domProperty->getAttribute('name') . '.png';
								$this->_dumper->dumpImage($property[$domProperty->getAttribute('name')]['basedata'],
														  $this->_dumpDirectory . $filePath . '/' . $fileName);
								
								break;
							default:
							case "int":
							case "string":
								$property[strtolower($domProperty->getAttribute('name'))] = $domProperty->getAttribute('value');
								break;
						}
					}
					
					$rowsetEquipment[$wid] = array_merge($rowsetEquipment[$wid], $property);
				}
			}
		}
		$this->_setEquipmentRowSet($rowsetEquipment);
	}
	
	/**
	 * すべての画像をエクスポート
	 */
	public function imageAction()
	{
		$directory = $this->_getDirectoryStructure($this->_expath);
	}
	
	/**
	 * 装備情報の登録
	 */
	protected function _setEquipmentRowSet($rowsetEquip)
	{
		$equip = new Model_TrnEquipment();
		$widList = $equip->getByWid(array_keys($rowsetEquip));

		$columnList = $this->_config->equipment->column->toArray();

		foreach ($rowsetEquip as $rowWid => $rowEquip) {
			$row = new Model_TrnEquipment();
			$row->wid = $rowWid;
			
			// 既に登録されてるデータの場合は ID をセット
			if (isset($widList[$rowWid])) {
				$row->id = $widList[$rowWid]->id;
			}
			
			foreach ($columnList as $sourceName => $columnName) {
				switch ($columnName) {
					case 'group_cd':
						$row->$columnName = substr('000' . $rowWid, -7, 3);
						break;
					default:
						if (isset($rowEquip[$sourceName])) {
							$row->$columnName = $rowEquip[$sourceName];
						}
						break;
				}
			}
			
			// 時間を取得
			$now = new DateTime();
			$row->update_datetime = $now->format('Y-m-d H:i:s');
			$row->update_user = 'admin';
			
			// 新規登録の場合のみ
			if (!isset($row->id)) {
				$row->since = $this->_config->version;
				$row->insert_datetime = $now->format('Y-m-d H:i:s');
				$row->insert_user = 'admin';
			}
			
			$row->save();
		}
	}
	
	/**
	 * アイテム情報の登録
	 */
	protected function _setItemRowSet($rowsetItem)
	{
		$item = new Model_TrnItem();
		$widList = $item->getByWid(array_keys($rowsetItem));

		foreach ($rowsetItem as $rowWid => $rowItem) {
			$row = new Model_TrnItem();
			$row->wid = $rowWid;
			
			// 既に登録されてるデータの場合は ID をセット
			if (isset($widList[$rowWid])) {
				$row->id = $widList[$rowWid]->id;
			}
			
			$row->name = $rowItem['name'];
			$row->description  = $rowItem['desc'];
			
			if (isset($rowItem['info']['price'])) {
				$row->price = $rowItem['info']['price'];
			}
			
			if (isset($rowItem['info']['slotMax'])) {
				$row->slot_max = $rowItem['info']['slotMax'];
			}
			
			// 売却不可フラグ
			if (isset($rowItem['info']['notSale']) && $rowItem['info']['notSale'] == 1) {
				$row->not_sale_flg = 1;
			}
			
			// キャッシュアイテムフラグ
			if (isset($rowItem['info']['cash']) && $rowItem['info']['cash'] == 1) {
				$row->cash_flg = 1;
			}
			
			// 時間を取得
			$now = new DateTime();
			$row->update_datetime = $now->format('Y-m-d H:i:s');
			$row->update_user = 'admin';
			
			// 新規登録の場合のみ
			if (!isset($row->id)) {
				$row->since = $this->_config->version;
				$row->insert_datetime = $now->format('Y-m-d H:i:s');
				$row->insert_user = 'admin';
			}
			
			$row->save();
		}
	}
	
	/**
	 * ディレクトリ構造取得
	 *
	 * @param	string	$directory	ディレクトリ名
	 * @return	array	ディレクトリ構造
	 */
	protected function _getDirectoryStructure($directory)
	{
		$structure = array();
		$fileList = $this->_getAllFiles($directory);
		foreach ($fileList as $file) {
			$xmlPath = $directory . '/' . $file;
			if (is_dir($xmlPath)) {
				$structure[$file] = $this->_getDirectoryStructure($xmlPath);
				continue;
			}
			$xml = simplexml_load_file($xmlPath);
			$structure[$file] = $this->_getXmlStructure($xml, $xmlPath . '/');
		}
		
		return $structure;
	}
	
	/**
	 * ディレクトリ構造取得
	 *
	 * @param	string	$directory	ディレクトリ名
	 * @return	array	ディレクトリ構造
	 */
	protected function _getXmlStructure($xml, $xmlPath)
	{
		$structure = array();
		if (count($xml)) {
			foreach ($xml->children() as $node) {
				$nodeName = (string)$node->attributes()->name;
				if (is_numeric($nodeName) && strlen($nodeName) > 7) {
					$nodePath = $xmlPath . $nodeName . '/';
				} else if ($nodeName == 'info') {
					$nodePath = $xmlPath;
				} else {
					$nodePath = $xmlPath . $nodeName . ' ';
				}
				if ($node->getName() != 'canvas') {
					$structure[$nodeName] = $this->_getXmlStructure($node, $nodePath);
					continue;
				}
				$canvas = array();
				$canvas['width'] = (int) $node->attributes()->width;
				$canvas['height'] = (int) $node->attributes()->height;
				$canvas['basedata'] = (string) $node->attributes()->basedata;
				$structure['canvas'][$nodeName] = $canvas + $this->_getXmlStructure($node, $nodePath);
				$nodePath = str_replace(array('.wz', '.img', '.xml'), '', $nodePath);
				$nodePath = str_replace($this->_expath, '', $nodePath);
				$nodePath = substr($nodePath, 0, (strlen($nodePath) - 1));
				$nodePath = str_replace(' ', '', ucwords($nodePath));
				
				$dumpPath = $this->_dumpDirectory . $nodePath . '.png';
				$this->_dumper->dumpImage($canvas['basedata'], $dumpPath);
			}
		} else {
			if (!is_null($xml->attributes()->value)) {
				switch ($xml->getName()) {
					default:
					case 'string':
					case 'uol':
						$structure = (string) $xml->attributes()->value;
						break;
					case 'int':
						$structure = (int) $xml->attributes()->value;
						break;
				}
			} else {
				$structure['x'] = (int) $xml->attributes()->x;
				$structure['y'] = (int) $xml->attributes()->y;
			}
		}
		return $structure;
	}
	
	/**
	 * ディレクトリ内ファイル名全取得
	 *
	 * @param	string	$directory	ディレクトリ名
	 * @return	array	ファイルリスト
	 */
	protected function _getAllFiles($directory)
	{
		$fileList = array();
		if (is_dir($directory)) {
			$fileList = scandir($directory);
		}
		
		// ディレクトリ名を削除
		// "." 同ディレクトリ
		// ".." 親ディレクトリ
		return array_diff($fileList, array('.', '..'));
	}
	
	/**
	 * ファイル名から WID 取得
	 *
	 * @param	string	$fileName	ファイル名
	 * @return	string	WID
	 */
	protected function _getWid($fileName)
	{
		return str_replace('.img.xml', '', $fileName);
	}
	
	/**
	 * ファイル名から XML の info を取得
	 *
	 * @param	string	$fileName	ファイルパス
	 * @return	array	パラメータリスト
	 */
	protected function _getInfoParameter($filePath)
	{
		$info = array();
		$dom = new Zend_Dom_Query(file_get_contents($filePath));
		$result = $dom->query('imgdir[name="info"]');
		foreach ($result as $element) {
			foreach ($element->childNodes as $node) {
				if ($node->nodeName == "#text") {
					continue;
				}
				
				$paramName = strtolower($node->getAttribute('name'));
				$info[$paramName] = $node->getAttribute('value');
			}
		}
		
		return $info;
	}
	
	/**
	 * ファイル名からモンスターの画像を出力
	 *
	 * @param	string	$fileName	ファイルパス
	 * @return	array	パラメータリスト
	 */
	protected function _createMonsterImg($filePath)
	{
		$info = array();
		$dom = new Zend_Dom_Query(file_get_contents($filePath));
		$result = $dom->query('imgdir[name="stand"]');
		foreach ($result as $element) {
			foreach ($element->childNodes as $node) {
				if ($node->nodeName == 'canvas' && $node->getAttribute('name') == 0) {
					$filePath = str_replace(array('.wz', '.img', '.xml'), '', $filePath);
					$filePath = str_replace($this->_expath, '', $filePath);
					$filePath = str_replace('Mob', 'monster', $filePath);
					$filePath = str_replace(' ', '', ucwords($filePath));
					
					$dumpPath = $this->_dumpDirectory . $filePath . '/stand0.png';
					$this->_dumper->dumpImage($node->getAttribute('basedata'), $dumpPath);
				}
			}
		}
	}
}
